{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# <center> Convolutional Neural Network\n",
    "\n",
    "### Convolutional Layers: [512] ; Dropout layer ; Dense Layers [512]\n",
    "\n",
    "CNN is trained on raw data"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## <font color = 'blue'> Get the data"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Stored variables and their in-db values:\n",
      "X_16_val                  -> array([[-0.86867832,  0.90982973, -0.41354501, ...\n",
      "X_32_val                  -> array([[ 0.58128519,  1.18391134,  1.03769373, ...\n",
      "X_32test_std              -> defaultdict(<class 'list'>, {0: array([[ 0.5812851\n",
      "X_32train_std             -> array([[-0.8119218 ,  0.28416571, -0.9279788 , ...\n",
      "X_test                    -> defaultdict(<class 'list'>, {0: array([[[ -1.08940\n",
      "X_test_std                -> defaultdict(<class 'list'>, {0: array([[-0.8686783\n",
      "X_train                   -> array([[[-0.00749793,  0.00696769,  0.00273202, ..\n",
      "X_train_std               -> array([[-0.8119218 ,  0.28416571, -0.9279788 , ...\n",
      "snrs                      -> [-20, -18, -16, -14, -12, -10, -8, -6, -4, -2, 0, \n",
      "y_16_val                  -> array([0, 2, 1, ..., 1, 4, 2])\n",
      "y_32_test                 -> defaultdict(<class 'list'>, {0: array([0, 7, 1, ..\n",
      "y_32_train                -> array([2, 4, 3, ..., 3, 0, 0])\n",
      "y_32_val                  -> array([0, 7, 1, ..., 1, 0, 3])\n",
      "y_test                    -> defaultdict(<class 'list'>, {0: array([0, 2, 1, ..\n",
      "y_train                   -> array([2, 4, 3, ..., 3, 0, 0])\n"
     ]
    }
   ],
   "source": [
    "import warnings\n",
    "warnings.filterwarnings('ignore')\n",
    "\n",
    "import matplotlib.pyplot as plt\n",
    "import numpy as np\n",
    "import tensorflow as tf\n",
    "from collections import defaultdict\n",
    "from time import time\n",
    "\n",
    "%store -r\n",
    "%store"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training data:  (80000, 2, 128) and labels:  (80000,)\n",
      "\n",
      "Test data:\n",
      "Total 20 (4000, 2, 128) arrays for SNR values:\n",
      "[-20, -18, -16, -14, -12, -10, -8, -6, -4, -2, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18]\n"
     ]
    }
   ],
   "source": [
    "print(\"Training data: \", X_train.shape, \"and labels: \", y_train.shape)\n",
    "print()\n",
    "print(\"Test data:\")\n",
    "print(\"Total\", len(X_test), X_test[18].shape, \"arrays for SNR values:\")\n",
    "print(sorted(X_test.keys()))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## <font color = 'blue'> Standardize the features"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Training set (80000, 2, 128)\n",
      "Test set corresponding to one snr value (4000, 2, 128)\n"
     ]
    }
   ],
   "source": [
    "from sklearn.preprocessing import StandardScaler\n",
    "\n",
    "sc = StandardScaler()\n",
    "_X_train = np.reshape(X_train, [X_train.shape[0], X_train.shape[1]*X_train.shape[2]])\n",
    "_X_train = sc.fit_transform(_X_train)\n",
    "\n",
    "X_train = np.reshape(_X_train, X_train.shape)\n",
    "print(\"Training set\", X_train.shape)\n",
    "\n",
    "_X_test = defaultdict(list)\n",
    "for snr in snrs:\n",
    "    _X_test[snr] = np.reshape(X_test[snr], [X_test[snr].shape[0], X_test[snr].shape[1]*X_test[snr].shape[2]])\n",
    "    _X_test[snr] = sc.transform(_X_test[snr])\n",
    "    X_test[snr] = np.reshape(_X_test[snr], X_test[snr].shape)\n",
    "    \n",
    "print(\"Test set corresponding to one snr value\", X_test[18].shape)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## <font color = 'blue'> Design and train the CNN"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Epoch 0 training accuracy : 0.2001953125\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_single_conv_dropout2\n",
      "Epoch 1 training accuracy : 0.2998046875\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_single_conv_dropout2\n",
      "Epoch 2 training accuracy : 0.357421875\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_single_conv_dropout2\n",
      "Epoch 3 training accuracy : 0.4150390625\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_single_conv_dropout2\n",
      "Epoch 4 training accuracy : 0.4697265625\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_single_conv_dropout2\n",
      "Epoch 5 training accuracy : 0.5048828125\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_single_conv_dropout2\n",
      "Epoch 6 training accuracy : 0.4921875\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_single_conv_dropout2\n",
      "Epoch 7 training accuracy : 0.4765625\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_single_conv_dropout2\n",
      "Epoch 8 training accuracy : 0.4931640625\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_single_conv_dropout2\n",
      "Epoch 9 training accuracy : 0.482421875\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_single_conv_dropout2\n",
      "INFO:tensorflow:Restoring parameters from ./CNN_single_conv_dropout2\n",
      "Training took 43.068458 minutes\n"
     ]
    }
   ],
   "source": [
    "height = 2\n",
    "width = 128\n",
    "channels = 1\n",
    "n_features = height * width\n",
    "\n",
    "feature_map1 = 512\n",
    "ksize_conv1 = 2\n",
    "stride_conv1 = 1\n",
    "conv1_dropout_rate = 0.3\n",
    "\n",
    "pool_layer_maps1 = 512\n",
    "\n",
    "n_fully_conn1 = 512\n",
    "dense1_dropout_rate = conv1_dropout_rate\n",
    "\n",
    "n_classes = 8\n",
    "  \n",
    "X = tf.placeholder(tf.float32, shape=[None, height, width])\n",
    "X_reshaped = tf.reshape(X, shape=[-1, height, width, channels])\n",
    "labels = tf.placeholder(tf.int32, shape=[None])\n",
    "training_ = tf.placeholder_with_default(False, shape=[])\n",
    "\n",
    "xavier_init = tf.contrib.layers.xavier_initializer()\n",
    "relu_act = tf.nn.relu\n",
    "\n",
    "# ------------------ Convolutional and dropout layers ----------------------------\n",
    "\n",
    "def convolutional_layer(X, filter_, ksize, kernel_init, strides, padding):\n",
    "    convolutional_layer = tf.layers.conv2d(X, filters = filter_, kernel_initializer = kernel_init,\n",
    "                                           kernel_size = ksize, strides = strides,\n",
    "                                          padding = padding, activation = relu_act)\n",
    "    return convolutional_layer\n",
    "\n",
    "conv_layer1 = convolutional_layer(X_reshaped, feature_map1, ksize_conv1, xavier_init, stride_conv1, padding = \"SAME\")\n",
    "\n",
    "def drop_out(layer, rate):\n",
    "    dropout_layer = tf.layers.dropout(layer, rate, training = training_)\n",
    "    return dropout_layer\n",
    "    \n",
    "conv1_dropout = drop_out(conv_layer1, conv1_dropout_rate)\n",
    "\n",
    "# ----------------- Pooling layers -------------------------------------\n",
    "\n",
    "def pooling_layer(convlayer, ksize, strides, padding, pool_maps):\n",
    "    pool = tf.nn.max_pool(convlayer, ksize, strides, padding)\n",
    "    dim1, dim2 = int(pool.get_shape()[1]), int(pool.get_shape()[2])\n",
    "    pool_flat = tf.reshape(pool, shape = [-1, pool_maps * dim1 * dim2])\n",
    "    return pool_flat\n",
    "\n",
    "pool_layer1_flat = pooling_layer(conv1_dropout, [1,2,2,1], [1,2,2,1], \"VALID\", pool_layer_maps1)\n",
    "\n",
    "# ----------------- Fully connected and dropout layers -------------------\n",
    "\n",
    "def dense_layer(input_layer, n_neurons, kernel_init, activation):\n",
    "    fully_conn = tf.layers.dense(inputs = input_layer, units = n_neurons, activation = activation,\n",
    "                                kernel_initializer = kernel_init)\n",
    "    return fully_conn\n",
    "        \n",
    "dense_layer1 = dense_layer(pool_layer1_flat, n_fully_conn1, xavier_init, relu_act)\n",
    "\n",
    "dense1_dropout = drop_out(dense_layer1, dense1_dropout_rate)\n",
    "\n",
    "# ----------------- Output softmax layer ---------------------------\n",
    "\n",
    "logits = tf.layers.dense(dense1_dropout, n_classes)\n",
    "softmax_activations = tf.nn.softmax(logits)\n",
    "\n",
    "# ----------------- Specify performance measure -------------------------------\n",
    "\n",
    "cross_entropy = tf.nn.sparse_softmax_cross_entropy_with_logits(logits = logits, labels = labels)\n",
    "loss = tf.reduce_mean(cross_entropy)\n",
    "optimizer = tf.train.AdamOptimizer()\n",
    "train_operation = optimizer.minimize(loss)\n",
    "\n",
    "correct_predictions = tf.nn.in_top_k(logits, labels, 1)\n",
    "accuracy = tf.reduce_mean(tf.cast(correct_predictions, tf.float32))\n",
    "\n",
    "# ---------------- Execution phase -------------------------------------------\n",
    "    \n",
    "n_epochs = 10\n",
    "batch_size = 1024\n",
    "n_train = X_train.shape[0]\n",
    "n_iter = n_train//batch_size\n",
    "\n",
    "acc_test = defaultdict(list)\n",
    "\n",
    "path = \"./CNN_single_conv_dropout2\"  \n",
    "saver = tf.train.Saver()\n",
    "\n",
    "start = time()\n",
    "\n",
    "with tf.Session() as sess:\n",
    "    tf.global_variables_initializer().run()\n",
    "    for epoch in range(n_epochs):\n",
    "        for iteration in range(n_iter):\n",
    "            rand_indices = np.random.choice(n_train,batch_size)    \n",
    "            X_batch, y_batch = X_train[rand_indices], y_train[rand_indices]\n",
    "            sess.run(train_operation, feed_dict={X: X_batch, labels: y_batch, training_: True})\n",
    "        acc_train = accuracy.eval(feed_dict={X: X_batch, labels: y_batch})\n",
    "        print(\"Epoch {} training accuracy : {}\".format(epoch, acc_train))\n",
    "        save_path = saver.save(sess, path)\n",
    "        saver.restore(sess, path)\n",
    "    saver.restore(sess, path)\n",
    "    for snr in snrs:\n",
    "        acc_test[snr] = accuracy.eval(feed_dict={X: X_test[snr], labels: y_test[snr]})\n",
    "\n",
    "print(\"Training took %f minutes\"%(float(time() - start)/60.0))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## <font color = 'blue'> Test the classifier"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "CNN's test accuracy on -20dB SNR samples = 0.1197500005364418\n",
      "CNN's test accuracy on -18dB SNR samples = 0.12250000238418579\n",
      "CNN's test accuracy on -16dB SNR samples = 0.12600000202655792\n",
      "CNN's test accuracy on -14dB SNR samples = 0.13500000536441803\n",
      "CNN's test accuracy on -12dB SNR samples = 0.13750000298023224\n",
      "CNN's test accuracy on -10dB SNR samples = 0.16975000500679016\n",
      "CNN's test accuracy on -8dB SNR samples = 0.2565000057220459\n",
      "CNN's test accuracy on -6dB SNR samples = 0.40400001406669617\n",
      "CNN's test accuracy on -4dB SNR samples = 0.4897499978542328\n",
      "CNN's test accuracy on -2dB SNR samples = 0.5214999914169312\n",
      "CNN's test accuracy on 0dB SNR samples = 0.5702499747276306\n",
      "CNN's test accuracy on 2dB SNR samples = 0.6575000286102295\n",
      "CNN's test accuracy on 4dB SNR samples = 0.6957499980926514\n",
      "CNN's test accuracy on 6dB SNR samples = 0.703249990940094\n",
      "CNN's test accuracy on 8dB SNR samples = 0.7135000228881836\n",
      "CNN's test accuracy on 10dB SNR samples = 0.7242500185966492\n",
      "CNN's test accuracy on 12dB SNR samples = 0.7082499861717224\n",
      "CNN's test accuracy on 14dB SNR samples = 0.7197499871253967\n",
      "CNN's test accuracy on 16dB SNR samples = 0.6949999928474426\n",
      "CNN's test accuracy on 18dB SNR samples = 0.7222499847412109\n"
     ]
    }
   ],
   "source": [
    "for snr in snrs:\n",
    "    print(\"CNN's test accuracy on {}dB SNR samples = {}\".format(snr,acc_test[snr]))  "
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## <font color = 'blue'> Visualize classifier's performance on test set"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAmMAAAGPCAYAAAAQptcZAAAABHNCSVQICAgIfAhkiAAAAAlwSFlz\nAAALEgAACxIB0t1+/AAAIABJREFUeJzs3Xl4VOX5//H3nUkChC1A2F0SF9wVtVptraXVVqyt1qUW\nKlVakbqibVUs1SqW4obfKgXbKq7Fn9a1btVqK2hr0dqqrQuIS6KAbGGHQDKZ3L8/ZgJDMpkMkNnO\nfF7XlYucMyfn8zwDF9yc555zzN0RERERkewoyvYARERERAqZijERERGRLFIxJiIiIpJFKsZERERE\nskjFmIiIiEgWqRgTERERySIVYyIFxMwONLOHzOwjM9tkZrVm9l5s30ktjm2K+3qoxWs/invtF3H7\nr27xc02xnGozm2FmO2VqrtuixXyazOy6bI9JRAqHijGRAmFmRwGvA6cBlUAJ0AvYCzgVOCHBjzXf\niPAUMzsgyeuJ9jd/lQC7AD8E/mFmZds5hXQ6g63HfEZ2hyMihUTFmEjhGE+0MIoAJwFdgd7A54Fr\ngY+T/KwBE7cxb6K7h4B9gU9j+3aOZecMM9sV+GL8LmCwmQ3LzohSZ2adsj0GEdlxKsZECseesV/X\nAS+4+yZ3X+Pu/3b3ie5+fRs/10i0QDnJzIZua6i7vw88Frdrl2THm9njsaXCRjMbELffzOyz2Gsf\nx/Z1NrPrzGyema0zs/WxJdhHzOzwFIf4faLzA7grbv+oNsZ3ipk9H1virTezhWb2qJn1jDumv5n9\n2szeN7ONZrbGzP5jZt+PO6Z5SfTFFudvtb/F8u+3zexOM6sFNsZe/6qZPR1bDl4XG9enZvYHM9s9\nwRy+YmZ/MrMlsWOXmNmfzazKzA6Ky5re4ucuinvtuym+vyLSDhVjIoVjQezXcuADM/utmZ1pZpXt\n/Nxq4Bm27+pYM4v7flk7xzYXRAbE/4M/DBhAdBnx7ti+m4le8dsTKAO6EF2CPRn4XIpj+17s18bY\nuRbHsk9teeXJzKYAjwDHEl3iLQYGAt8GesaO2R34L3AxsAdQCnQDhgJfaZGdbJm3rf13AKNj+U2x\n/YcBxxMtdMti4xpMdLn1FTPrHTeHi4C/AicCfWPH9gWOA3Z29/8CL8UOP6PFsnLz78cKti6wRWQH\nqBgTKRy3EP3H24GdgB8B9wAfm9krZnZQkp9tbtL/ppkdui2hZrY30eIIYD3wVDs/8mdgSez778Xt\nb/7eiY4b4Eux7VeJFhRdgb2B84G5KYzt0NjxDrzo7iuBx2Mv9yBasDQfexjwk9ixa4j23vUgWgD9\nGKiLHfoboF/suMeIFmTdgaOBra6C7YDjiBZdzb9nz8fO35/oUnQfYHLstb7ErvKZ2WDgptj+MDCW\naFE3kGhP3/LYa7fEfu1OrH8u9uGLI2Pzus/dwx00F5GCp2JMpEC4+zPAMcAsoleB4hvWjwSeStBc\nb7GffZMtRVSqV8euMbMm4D1gV+BD4AR3r21nnBHgD7Hsz5nZbmZWApzClqKp+Spfdey4fYkWjKOI\nFiJ3ufusFMZ4Ztz3j7b4FbZeqjwx7vub3f1xd9/g7ovcfaq715pZZ6JXzSBaeJ7p7tXuXufur7j7\nzBTG1J4p7v5Xd69393dj+z4jWjTNATYAK4Gfx/3MXrFfhxO9Ugcw093vdPe17r7M3e919+YC9kng\nI6Lv7bmxfSPZcoXzzg6Yh4jEqBgTKSDu/pK7HwtUEP305O+IXiGB6LLWkS1/JO77q2O/Hg8ckUpc\n3BdElxBL2z58K/G9W9+LZfaKbc+Ie+3HwL+IXqG6CLgd+CewyMyOJQkzKwJOj9v1oZntR3QJbgPR\nwmN43BJf/7hj27rq1pvosp8Dn7r7xmRjSDCmUAqHvdXiZ4zoFbdzgd2Ivsfx7ztE33vYeg7vtRXg\n7k70Ch/A0Fj/XfMS5Wvu3ubPisi2UzEmUiDMrHvz97GrIc+5+wXAvXGH9W79k5t/5i3gT0SLlITN\n7S1MBDoRvWITIVrsPZ7KvcZiTf+vxjZHxr4g2r/2p7jjPnb3I4BBwNeI9mktJnp17Dck93WixYnH\n5vQi8DbRYqdr7JhiYETs+6VxP7tPG+dcyZYPPOwSu1LWlobYr/HH7NbOmCHWtB/nwNh4HHgX2DX2\nKdZEn1pNZQ7N7gLWxr6/ATgklnF7CmMUkW2gYkykcPwp9um6E8yswsyKzWx/or1Gzdrrs7qG6D/I\nKf3d4e6N7v4g0PypvG5AW5/abOkuokXN3kTvg+bA/e7eXMRgZpea2elEr/z8A3iI6JKd0c6nNol+\ninLzUNv4gi2F55PNscBPzOxkM+tqZoPM7EIzq3D3TcALcXO9L/YJxTIz+3z8pymBT2LnOsDMdo4t\nxU5K4X1pqTHu+3qgLna7jgkJjn2OaBFowPfN7Idm1tPM+prZ981sc4Hm7uvZ8nvw5dju9UTfYxHp\nQCrGRApHKdGrVE8R/URjA/A/ov1EDvzJ3d9p8TPxn4LE3d8m2lNlbJtfEr3KYsAIMzswhZ95kGhT\nvBG9QgVbPkXZ7LjYcR8Dm4heFTuU6Hyea+vEZtaVLVeO6oFydw/FfwGLYtmfN7Pd3f11op/edKKf\nnHyU6G1CFgK3Em2oBxjHlg8gnEa092o90X6u+E9T3h/7tWvsmNXAN5qH2Oa70to8thTRhwK1RHvp\nmq9ybj6Xuy8CLiP6QY5ioku+q4heMbuHaLN/vKls+dCHAw+4ex0i0qFUjIkUjiuJfkrudaJXjxqI\n9ka9CfyMLctxzVpeIWp2DdFlx5Rvy+DuK4ApbFkSbPdxQ7ErM4/EjeG/sQ8SxLuH6G03FhBdvmsA\nPiBaNJ1J204hejXNgSfcfV2CY2bS4uqYu19G9CrdX4kuSTYQLdoeJ/oJS9z9I6K3sbgVmE+0SFwH\nvEH0wxPNrgf+L/bz9URvJ/FF2n7fE+1r/sDDt4BniRa8y4n+Po9LdC53/w3RD3I0F+VhosXYc2y5\n/UnzsTXAE2wp6OL79USkg1i0T1NERGRrsQ8UzAKOAv7j7odleUgigVTc/iEiIlJozGwe0Q9C9CF6\nZe2arA5IJMB0ZUxERFoxswjRfrFPgevd/Y4sD0kksFSMiYiIiGSRGvhFREREsihve8bMTJf0RERE\nJG+4e8Lb1uT1lTF3z9jX1VdfrTzl5VyW8pSnvMLJC/LcCiEvmbwuxjKppqZGecrLuSzlKU95hZMX\n5LkVQl4yKsZEREREsih0zTXXZHsM22XixInXZHLs5eXlVFZWKk95OZWlPOUpr3Dygjy3QsibOHEi\n11xzzcREr+XtrS3MzPN17CIiIlJYzAwPYgN/Js2ePVt5ysu5LOUpT3mFkxfkuRVCXjIqxkRERESy\nSMuUIiIiImmmZUoRERGRHKViLEVBX8tWXn5mKU95yiucvCDPrRDyklExJiIiIpJF6hkTERERSTP1\njImIiIjkKBVjKQr6Wrby8jNLecpTXuHkBXluhZCXjIoxERERkSxSz5iIiIhImqlnTERERCRHqRhL\nUdDXspWXn1nKU57yCicvyHMrhLxkVIyJiIiIZJF6xkRERETSTD1jIiIiIjlKxViKgr6Wrbz8zFKe\n8pRXOHlBnlsh5CWjYkxEREQki9QzJiIiIpJm6hkTERERyVEqxlIU9LVs5eVnlvKUp7zCyQvy3Aoh\nLxkVYyIiIiJZpJ4xERERkTTLqZ4xMxtuZvPMbL6ZjU/w+i5m9lcz+6+ZvWhmgzI9RhEREZFMyWgx\nZmZFwDTgOGA/YKSZ7d3isCnAPe5+EHAtcH0mx9iWoK9lKy8/s5SnPOUVTl6Q51YIeclk+srY4cAH\n7v6Ju4eBB4GTWhyzL/AigLvPTvC6iIiISGBktGfMzE4FjnP3sbHtUcDh7j4u7piZwGvu/hszOwV4\nGKhw91UtzqWeMREREckLyXrGijM9lgT7WlZUlwHTzGw08DKwCGhMdLLRo0dTWVkJQHl5OUOHDmXY\nsGHAlsuP2ta2trWtbW1rW9uZ3m7+vqamhna5e8a+gCOA5+K2rwDGJzm+K/BpG695Js2aNUt5ysu5\nLOUpT3mFkxfkuRVCXqxuSVjvFLVfrnWo14E9zGxXMysFRgBPxh9gZn3MrPkK2s+AuzI8RhEREZGM\nyfh9xsxsOHAr0Q8P3Onu15vZROB1d3861ld2HdBEdJnyAo82+7c8j2d67CIiIiLbI1nPmG76KiIi\nIpJmOXXT13wV35CnPOXlSpbylKe8wskL8twKIS8ZFWMiIiIiWaRlShEREZE00zKliIiISI5SMZai\noK9lKy8/s5SnPOUVTl6Q51YIecmoGBMRERHJIvWMiYiIiKSZesZEREREcpSKsRQFfS1befmZpTzl\nKa9w8oI8t0LIS0bFmIiIiEgWqWdMREREJM3UMyYiIiKSo1SMpSjoa9nKy88s5SlPeYWTF+S5FUJe\nMirGRERERLJIPWMiIiIiaaaeMREREZEcpWIsRUFfy1ZefmYpT3nKK5y8IM+tEPKSUTEmIiIikkXq\nGRMRERFJM/WMiYiIiOQoFWMpCvpatvLyM0t5ylNe4eQFeW6FkJeMijERERGRLFLPmIiIiEiaqWdM\nREREJEdlvBgzs+FmNs/M5pvZ+ASv72xmL5rZG2b2lpkdn+kxJhL0tWzl5WeW8pSnvMLJC/LcCiEv\nmYwWY2ZWBEwDjgP2A0aa2d4tDrsS+KO7HwKMBG7L5BhFREREMimjPWNmdgRwtbsfH9u+AnB3vyHu\nmN8CH7v7TWZ2JHCTux+V4FzqGRMREZG8kKxnrDjDYxkMLIjbXggc3uKYicDzZjYOKAOOzdDYRERE\nRDIu0z1jiSrClpe3RgJ3u/vOwAnAzLSPKgVBX8tWXn5mKU95yiucvCDPrRDyksn0lbGFwC5x2zsB\nn7U45myiPWW4+6tm1tnMKty9tuXJRo8eTWVlJQDl5eUMHTqUYcOGAVve5I7afuuttzr0fMoLdp62\nta1tbXf0djPl5Ude8/c1NTW0J9M9YyHgfeAYYDHwL2Cku8+NO+YZ4CF3v9fM9gFecPedEpxLPWMi\nIiKSF3LmPmPuHgEuBJ4H3gUedPe5ZjbRzL4ZO+xS4Bwzewu4Hzgrk2MUERERyaSMFmMA7v6cu+/l\n7nu6+/WxfVe7+9Ox7+e6+1HuPtTdD3H3v2V6jIm0vKypPOXlQpbylKe8wskL8twKIS+ZjBdjIiIi\nIrKFnk0pIiIikmY50zMmIiIiIltTMZaioK9lKy8/s5SnPOUVTl6Q51YIecmoGBMRERHJIvWMiYiI\niKSZesZEREREcpSKsRQFfS1befmZpTzlKa9w8oI8t0LIS0bFmIiIiEgWqWdMREREJM3UMyYiIiKS\no1SMpSjoa9nKy88s5SlPeYWTF+S5FUJeMirGRERERLJIPWMiIiIiaaaeMREREZEcpWIsRUFfy1Ze\nfmYpT3nKK5y8IM+tEPKSUTEmIiIikkXqGRMRERFJs2Q9Y8WZHoyIiEi+q66uYfKUGdSuDlNRXsKE\nS8dQVVWZ5VFJvtIyZYqCvpatvPzMUp7ylJf5vOrqGkaOvZH5DaOoWX8I8xtGMXLsjVRX16Q1N4jv\nZTbyqqtrOOeCKznq2JGcc8GVaf99S4WKMRERkRQsWhbm1bc3ct5lv6NT5ThCJWUAhErK6FQ5jslT\nZmR5hB2juVi5ctLvc6ZY6SjxhfSGrt/OWCHdHvWMiYhIwWuMOMtWRVhS20jlwBJ69wy1Ouayqcv4\nz7xNVP/r/6g6/CetXu+5ZjqP33/D5u3a1Y2Udw9RHErYJpSTmouV5mIzEq6jvmYqD9x+eSCWYc+5\n4ErmN4zaXEgDRMJ1DCmdyR3TJ6U1Wz1jIiISaNvTw/XYrHX84606Fq9oZPmqCE2x/99PGN2HYw/v\n2ur4/XYrxQwaakqJhOta/YNeUV6y1fFX/q6W6s8aqBpUyp47l7DHzqXsGfsqKc5ugeburFgTochs\nq8Jz8pQZCa/6/eTK3/Pg3b+iU2l+Lai5O58uaWTXgdHfm9rVYUI9y7Y6JlRSRu3qcDaGt1l+vatZ\nFNS1c+Xld5bylKe8xD1c3xp1PVfd+hZXTFvGy2/WJfy5z5aHeeuDepaujOBA3/IQB+zRiS6dEhdK\no79Zzo0X9eMP08+nvmYqkXAdqxbN2Xz1aMKlYzYf6+7Uh51wI8z/tIFnXtnArQ+u4sKblrJiTWS7\n5rkj7+Xcmnp+++gqrvrdcs6etJgTfryQ0yd8xh//unar42pXhzcXYqsWzQGixcpb72/k25ct4tl/\nrt/uMbSno/6sNDU573xUz22PrGLkVZ9x9qTFrFwbfc8rykuIhKN/Hprnl6iQzjRdGRMRkZzn7qxe\n38TSFY10LyticL8t/3gmuprTZ99LmDnzdqoOu4Q9dynl6IPLWp3zG1/sxuf378LAimL69SqmtCS1\nq1VVVZU8cPvlTJ4yg7kbPmJI6dtMaLGMZ2bcfdVA1m9s4qMFDXywsIEPF4T5rLaR/r1bL4FGmpwx\nv1rCTv2KN18922PnEip6hqip+SSa9f5H7PPwX7e66lff0MRntY3Rr+WN9O1VzLBDWs+1ZnGYh/+2\nbqt9PboWUdRiyhXlJaxsaH3Vr3u3YurDzqC+uV023PvMGp7+x/qtCt4+PUN8tryR3j1CTLh0zOZl\nWGBLIX375dkaMpCFnjEzGw7cQvSq3J3ufkOL1/8P+ArgQFegr7v3TnAe9YyJiOSojrj1w5y3N/LE\nS+tYsqKRpSsj1Iejf+d/55junHdqr83HnXzGeNb0vKDVz9fXTOXG669l98GlDOiT20XEp0vCjL52\ncav93UOLWTr3XjpVbd3D9bPx47j/xe7Urt76Ktvn9+vMdRf0a33+pWH+8WYdg/oWM6hvCYP6FtOt\nS+vFsWQ9Y9177USv7iFCCXrgfjZ9Gb17hDjigC4cundnyjpnZ+HtlgdW8uTf19Ovd4gvH1zG0QeX\nsU9lKUVxVWe2bkuSrGcso8WYmRUB84FjgM+A14ER7j6vjeMvBIa6+5gEr6kYExHJQW39g37HrZfS\nVDKIpSsjLF3ZyNJYkXXgHp34/jd6tjrPs3PWc9MfVm7e7tbFGNCnmK9+risjvt5j8/5sNmV3lEiT\ns2BpIx8uaOCD2NeHCxpY8Mat9NhjTKu59W+4j9qu5xIqgoEVxQyqKGZg32L22bWUrx/RbYfGsq3F\nyoo1Eb7zs0Wbt0uK4aA9O3PE/l046ehuCYu37RVudN54fxPFIePQvTu3en3B0jB1m5oYskspZrn1\nwYlcKsaOAK529+Nj21cA3vLqWNzxrwC/cPe/JXgto8XY7NmzGTZsmPKUl1NZylNetvMiTc6a9U2s\nWhth1boIq9Y2cdvUSawsO4tQSRmrFs2h1+AjiYTr6LHuHjb0Pr/VOY7YvzOTz299NWfZykY+XNjA\ngD7F9O9dTNcEV3Jg6+Jv7bL/0qPfQRn7BGA6f//cnZNGXsH63tGrfs3vJUCP1dP57dRf0a9X4itV\nHSHVubk7NYvDzPnfRua8s5H3qhtwh4F9Qsy8dlDKRVFbeQ1h5/W5G3n5jTr++fZGNmx0DtijE7f+\npP82zii1vHTJpU9TDgYWxG0vBA5PdKCZ7QJUAi+mf1giIsHWfLUjUd9RS40RZ/W6CKvWRYus4mLj\nkL1aX4X499yNXDFt+eZPITZbvmATffdv/Ym1hnAT+1aV0j9WXA3oHaJ/n2J26pf4n6J+vYvp17v9\nf6aqqtrv4cpHZkb/PiWsSdDD1bdXCQMrcmPp1cyoGlRK1aBSvje8J2vWR3jt3U00NXnCQmxxbSPv\nVddz2L6d6dE1lPTP5sJlYX503RI21m/5Q7bboBI+t09n3BOfPx9l+srYacDX3X1sbHsUcJi7X5zg\n2MuBwYlei73uZ511FpWVlQCUl5czdOjQzVVu86cytK1tbWu70LcfeOBBfjnlAfoecgOhkjJWfDKb\n8JJHeeaRW6mqqtx8fP/KI/nZ9OV8Mv8VgM1XYXo2/ZuLR/Rudf5Bu32Bc69fQsOK1+jWtYh9DzyK\nXj1C/Omui2jseTx9do0ev2rRHJoa6zm8cj53TJ+U9fcjn7arq2s44bSLKRlwKn12HUYkXMfyN8Zz\n1aUjGTlyRNbHtz3bV974NM+8soE+Ox/Jzj2XMvuJX9Jj19MSzq+pyfnKqEfo0bWIEacey5cOLuPj\nua/k1Hza2m7+vqamBoB77703p5Ypr3H34bHtNpcpzewN4Hx3f7WNc6lnTEQkBd/74QQWhc5st6fq\nk8VhfvDLxZhBebcienUP0atHiN0Gl2zVML/5HE2OO61uahr0G4dmWtCegzn7jTqe+vs6/vdBPR++\ndgu7DB2b9M/m+romupUlXqLOJ8mWKTM9u9eBPcxsVzMrBUYAT7Y8yMz2AsrbKsSyIb7SVZ7yciVL\necpLZsPGJq763XLm/K8u4b2jWt7ocqd+xTxy/WCe/83OPHrDTsy4ciA3jeuXsBADCBVZwrvLV1VF\nlw2HlM6kYf54hpTOzFghFqTfv2ZVVZXcMX0SF59zPHdMn5SxQixdcxt2SBk3X9yfx2/aiV0Hhtr9\ns5muQizTf1aSyeiCs7tHYp+QfJ4tt7aYa2YTgdfd/enYoSOABzM5NhGRoCnrbCxd2UhRUVFKd4wP\nhYzePVrfA2t7VFVVbl6SbF6+EYnXrUsRe+7cifkJeuKyfRPWTNOzKUVEAuzDBQ2sW7WA8356s5YN\nJecU0pJ2ztzaoiOpGBMRgbUbIjz58no6lRrfOaZHm8cFre9IgqNQ/mzmUs9Y3gpiH4Ly8j9LeYWb\nt2RFI9MeXsWIKz/jrqfWcP9za9lY39Tm8VVVweo7KsS8oM6tqqow/mwmkxs3KRERkZQ0Rpwb71vB\ni/+poylWe31un85892s96FwajHsuiRQaLVOKiOSZ8dOW8Z95m/jqoWWcfmwP9ti5NNtDEpF2qGdM\nRCRAPlkcplOp5fzDr0VkC/WMdYCgrtUrL7+zlBfMvI31TTw2ax33PL064c/sOrBkuwuxXJif8nI/\nS3mZpf9WiYjkiFXrIjw+ex1PvryetRuaKCmGE4/u3mH3/hKR3KRlShGRLNjq4/w9Sxi872m8+kEf\nGsLRv9f2rSplxNd68IUDu1BUpMZ8kXynnjERkRyS6EaXS/53C32GnMlXv7gnI77Wg/1375TtYYpI\nB1LPWAcI+lq28vIzS3n5mTd5yozNhdiqRXMIlZQx4MBLqCx5mknn9k1rIRbE97NQ8oI8t0LIS0bF\nmIhIhtWuDm/1LD6IPhx5Y30kSyMSkWzSMqWISAbNrann2msn8lnozFYPRx5SOpM7pk/K4uhEJF20\nTCkikgM+WtjA+N8so7b4W2z46FYi4TqAzQ9HnnDpmCyPUESyQcVYioK+lq28/MxSXv7kfbokzGVT\nl7F+o3PEoXvwwO2XM6R0Jg3zxzOkdCYP3H55Rp7JF5T3sxDzgjy3QshLJqX7jJnZ3u4+L92DEREJ\nos9qG/nprctYvb6Jw/btzFU/rKC0pC93TJ/E7NmzGTZsWLaHKCJZlFLPmJk1AXOAGcBD7r4h3QNr\nj3rGRCQfbGpo4uxfLmbxiggH7tGJ6y/sS+dSLUqIFJqO6Bk7EPgXcAOw2MxmmNmRHTVAEZGg6lxa\nxMjjerJvVSmTz1chJiKtpfS3gru/4+4/BgYBPwAGAC+b2Xtm9lMz65fOQeaCoK9lKy8/s5SXH3nf\nPKobt/60P2WdW/+VG4T5KS94WcrLrG36L5q7N7r7o8DJwKXAbsBNwKdmdo+Z9U/DGEVE8l5IjzQS\nkTZs033GzOxA4IfAGUAYuA+4k+gVs2uALu5+RMcPM+FY1DMmIiIieWGHn01pZucTLcIOAl4g2sj/\npLs3xh2zM1Dt7il9QnNHqRgTkVzTEHZu+MMKvntsD4bsUprt4YhIDumIBv4rgKeB3dz9G+7+WHwh\nFrMMuGAHxpnTgr6Wrbz8zFJe7uQ1RpyJM2qZ9e86Jt1VSySS2n8W82V+yst+XpDnVgh5yaR6FWvX\n9i5DuXs98PsdH5KISH6JNDnX3bOCOW9vpEfXIq45p4JQSD1iIpKaVJcpxwLr3P2BFvtHAt3c/Y40\njS/ZmLRMKSJZ19TkTLl/Jc/N2UBZZ+Pmi/ux166dsj0sEckxHbFMeSmwJMH+RbHXtmUww81snpnN\nN7PxbRxzupm9a2Zvm9nMbTm/iEgmvVfdwF9e3UDnUuO68/uqEBORbZZqMbYLUJ1g/6ex11JiZkXA\nNOA4YD9gpJnt3eKYPYDxwJHufgBwSarnT6egr2UrLz+zlJf9vP1378SE0X345bl9OWCPzmnP21HK\ny9+8IM+tEPKSSbVnbBlwAFDTYv9BwIptyDsc+MDdPwEwsweBk4D4516eA0x397UA7l67DecXEcm4\nYw7rmu0hiEgeS7Vn7EbgO8CZwD9iu78E3As85u4/TSnM7FTgOHcfG9seBRzu7uPijnkcmA98keiV\nu4nu/pcE51LPmIiIiOSFZD1jqV4ZuwrYE3gJaIjtKwGeAiZsy1gS7GtZURUDewBHE10C/buZ7dd8\npUxEJJvWbojQo2so28MQkQBJqRiL3bbiZDM7ABhKtKh6w93f2ca8hWzdY7YT8FmCY+a4exNQY2bv\nEy0E/9PyZKNHj6ayshKA8vJyhg4dyrBhw4Ata8EdtX3LLbek9fzKC05efB+C8oKV19DlMKY9tJKT\nD5lL1eDSwM1Pebmd1zJTebmd1/x9TU0N7XL3jH0BIeBDYFegFHgL2KfFMccB98S+rwA+AXolOJdn\n0qxZs5SnvJzLUl7m8l56Y4Mfc/4n/pXzPvGH/rom7Xnporz8zQvy3AohL1a3JKyPUn42pZlVAqcQ\nvbJV2qKgOz+lk0TPMxy4lWg/2J3ufr2ZTQRed/enY8fcDAwHGoFJ7v5wgvN4qmMXEdkRr76zkV/8\nfjmNEfj+8T34wbfKsz0kEckzHfFsyq8BTxL91ON+wH+B3Yhe6fqXu3+944abGhVjIpIJb76/iZ/d\ntpyGsPOdY7pz7inlmOnu+iKybTripq+Tgevd/WCgHvgu0StkLxEt0gIvfg1YecrLlSzlpT9v1boI\njRHnW0cBFPQaAAAgAElEQVR1S0shlu35KS9/8oI8t0LISybVT1PuDYyIfd8IdHH3DWb2C6LF2LR0\nDE5EJNu++rmuDKwoZq9dSnVFTETSItVlyiXAV9x9rpm9B1zh7k+a2YHAP929W7oHmmBMWqYUERGR\nvNAR9xn7F/AFYC7wHHCTme0DnBp7TUQkr1VX1zB5ygxqV4epKC9hwqVjqKqqzPKoRKQQpNozdhnR\n21AAXA38Ezib6GOSzk7DuHJO0NeylZefWcrrGNXVNYwceyPzG0ZRs/4Q5jeMYuTYG6murkl7dhDf\nT+Xlf5byMqvdYszMioHBwMcA7r7O3X/g7kPc/ZvunugB4iIieWPyTTPoVDmOUEkZAKGSMjpVjmPy\nlBlZHpmIFIJUe8Y2Eb05a84UXuoZE5GOMP/TBk45Yzz9Dvhxq9d6rpnO4/ffkIVRiUjQdMStLd4B\nqjpuSCIi2ffEy+s474YlbNhkRMJ1W70WCddRUV6SpZGJSCFJtRibQLRpf7iZ9TWzsvivdA4wVwR9\nLVt5+ZmlvB3zub0707nUGHP2WWz6eCqRcB2rFs0hEq6jvmYqEy4dk7bsZkF6P5UXnCzlZVaqn6Z8\nLvbrn4FEa4OhjhmOiEjmDO5XwoO/Gkz3sp353nGXM3nKDOZu+IghpW8z4fbL9WlKEcmIVHvGjkv2\nurv/pcNGlCL1jIlIqhbXNlJUBP17p/r/TxGRjrXDz6bMRSrGRKQ9G+ubeOD5tfzxhbUctm8XJp3b\nN9tDEpECtcMN/Ga2b7Kvjh1ubgr6Wrby8jNLeYm5O7P+vYHRExcz89m1hBuhrJMRbmz/P3D5MD/l\nFWZekOdWCHnJpHrN/h2ivWLNFV3Lv9HUMyYiOcHd+dn05fzrvU0A7LlzCRed3pv9d++U5ZGJiCSW\nas/YXi12lQAHA+OBn7n7U2kYW3tj0jKliCR091OrefLv6zn7xHKO/0JXQkV6wLeIZFfaesbM7Hii\nxdjR232S7c9WMSYiCW1qaCLcCN3LUr17j4hIenXETV/b8gFw6A6eIy8EfS1befmZVeh5Hy5oINF/\nyjqXFm13IZZL81Oe8rKVpbzMSrWBv6zFV1cz2wO4FvgwvUMUEdna0pWNXDujlrHXLWHO2xuzPRwR\nkR2Sas9YE4lv9roU+K67/72jB9YeLVOKFJ76hiYe+us6/t9f1lIfdjqVGOefVs63vtQ920MTEUkq\n2TJlqp+m/AZbF2NNwHLgPXdv2MHxiYi0Ul1dw+QpM6hdHaaivISzzjqL254qY8mKCABfObSMsSeX\n60auIpL3UlqmdPfn3P0vcV8vuPtbhVSIBX0tW3n5mRXUvOrqGkaOvZH5DaOoWX8I8xtG8dMJv2b9\n6gXsNriEX1/Sj6vOrkhLIRbE91N5wcgL8twKIS+ZVHvGxprZyAT7R5rZOR0/LBEpZJOnzKBT5ThC\nJWUAhErK6Fw1jh4bn+L3VwzgoCGdszxCEZGOk2rP2HzgR+4+q8X+o4E73L3lfcjSTj1jIsFTu7qR\n51/bwG+n/pKSXce1er3nmuk8fv8NWRiZiMiO6YiesV2A6gT7P429JiKyXRrCzpy3N/LsnPX8+71N\nNDmsWOP0DddtvjIGEAnXUVFeksWRioikR6o34lkGHJBg/0HAio4bTu4K+lq28vIzK9/zVq+LcPqE\nRUycUcu/3t1EUREcfXAXJl11DvXVU4mE61i1aA6RcB31NVOZcOmYDstuSz6/n8oLdl6Q51YIecmk\nemXsQWCqma0G/hHb9yXgFuCP2xJoZsNjP1cE3OnuN7R4/SzgJmBhbNc0d79rWzJEJD+Udw8xsKKY\ninLn+CO7cuzhXenZLQT05eAhlzN5ygzmbviIIaVvM+H2y6mqqszugEVE0iDVnrFORAuyk4DmT1CW\nAE8Rvc9YfUphZkXAfOAY4DPgdWCEu8+LO+Ys4FB3b90wsvW51DMmkgciTc5/5m5icL9iBvdtvcy4\nvq6Jrl0MMz0/UkSCa4d7xmLF1slmtj/RB4Qb8Ia7v7ONYzkc+MDdP4kNrLnAm9fiOP2tLJLnFi4L\n85c5G/jLaxuoXR3htK925/zTerU6rpueHykiBS7VW1sUmVnI3d9x9z+4+33u/o6ZhWJXu1I1GFgQ\nt70wtq+lU8zsLTN7yMx22obzp03Q17KVl59ZuZj34YIGLv6/pZx5zWLu/8taaldHGNS3mIEV23dP\nsFybn/KUl628IM+tEPKSSfVvx0eAOUR7ueJdAnwBODXF8yS64tVyrfFJ4P+5e9jMfgTcS3RZs5XR\no0dTWVkJQHl5OUOHDmXYsGHAlje5o7bfeuutDj2f8oKdV8jb3bsW8feXZ1NSbJxy4jEMP7IrKxfO\nwTAg++PTtrbzdbuZ8vIjr/n7mpoa2pNqz9hy4Kvu/naL/fsDf3P3/u2eJHr8EcA17j48tn0F4C2b\n+OOOLwJWunt5gtfUMyaSQS0fT3Tej37AwQfslrDX69W3N3Lgnp0o61yUhZGKiOSeZD1jqf5N2Y0t\njfvxGoEe2zCW14E9zGxXMysFRhC9EhY/2AFxmycB723D+UUkDeIfT7Sm5wXMbxjFt8+8gWdfmp/w\n+CMO6KJCTEQkRan+bfkOcHqC/aezDcWSu0eAC4HngXeBB919rplNNLNvxg4bZ2bvmNmbsWNHp3r+\ndGp5WVN5ysuFrEzlxT+eaNWiOYRKyqg67CdMnXZ32rOD+H4qT3m5nqW8zEq1Z2wS8IiZVQIvxvYd\nA4wCvrstge7+HLBXi31Xx30/AZiwLecUkfRatjJMqFfZVvtCJWV06aRWARGRHZVSzxiAmX0buJLo\nXfcB/gv8yt0fT9PY2huPesZEMuTMc37OJ3y/1eOJhpTO5I7pk7I4MhGR/JCsZyzlYizXqBgTyZzq\n6hpOH3MjZbtFlyqbH0/0gO6KLyKSko5o4C94QV/LVl5+ZmUqr6qqkodmXM6Q0pk0zB/PkNKZGSvE\ngvh+Kk95uZ6lvMxKqWfMzIqBy4CRwC5Aafzr7l6W6OdEJDiqqiq5Y/okZs+evfl+OiIisuNSvc/Y\nJKKfarwJuB64FqgCTiF637BpaRxjW2PSMqVIGjQ1OS+/WceXDynT8yJFRDrIDveMmdnHwEXu/oyZ\nrQOGuvtHZjYO+IK7j+jYIbdPxZhIx2tqcn79wEqeeWUDI77WnbEnt36WpIiIbLuO6BkbADTffX89\n0DP2/dPA8Ts2vPwQ9LVs5eVnVkfmuTvTHl7FM69soLTE+Ny+XdKalyrlKU95mc9SXmalWowtJFqQ\nAXzMlmdFHgrUd/SgRCSz3J3fPbaaP720npJi+OWPKjhkr87ZHpaISEFIdZnyZmC1u//SzEYC9wEf\nEu0b+427X5beYSYck5YpRTrIIy+u5bZHVlMcgolj+3LkAYmviomIyPbp8PuMmdmXgS8C8939kR0c\n33ZRMSbScVauiTB++jLO/EZPvjRUH44WEeloHX6fMXd/yd0nZ6sQy4agr2UrLz+zOiqvd88Qvxs/\nIKVCLB/npzzlBSEvyHMrhLxkdNNXEQEgFNJtLEREskGPQxIRERFJMz0OSUQ2e/af67n1jytpatJ/\nZkREcoGKsRQFfS1befmZta15L7y2gSn3r+SJl9bzn3mb0p7XEZSnPOVlPkt5mZVSMWZmfzazngn2\ndzezP3f8sESko83+zwZuuG8F7jDmxJ4c1sZNXUVEJLNSvc9YBBjo7sta7O8LfObuJWkaX7IxqWdM\nJEX/eKuOa2bU0tQEZ36jB6O/WZ7tIYmIFJRkPWPF7fzgvs3fAkPMrCLu5RAwHPisQ0YpImkRaXL+\n8Owamppg5Nd7cNYJrS5yi4hIFrW3TPkO0WdSOvBS7Pvmr/8CvwSuS+cAc0XQ17KVl59ZqeSFiowb\nL+rHeaeWM+aknpjt2C0scm1+ylNeoeQFeW6FkJdM0itjwD5Er4q9B3wJqI17rQFY7O7b1wUsIhnT\ns1uI7xzTI9vDEBGRBFLtGevk7jn1QHD1jImIiEi+6Ij7jB1vZl+NO+HlZvahmT0Ra+IXkRyxaHlY\n9xATEckjqRZjk4BSADM7iGiv2H1Ab+Dm9AwttwR9LVt5+ZnVMm/+pw2cd/0Sbpq5kkiaCrIg/94p\nT3m5nBfkuRVCXjLt9Yw1qwTmxb4/BXjC3a81s6cB3WdMJAd8vKiBy3+zjPUbnQ0bm9AqvohIfki1\nZ2wlcJS7v2dm/wDuc/fbzawSeM/dy1IONBsO3EL0qtyd7n5DG8edBjwEfM7d30jwunrGRGI+XRLm\nx79eyqp1TRyxf2cmju1LSbEe/C0ikiu2+z5jcV4BbjCzl4HDgRGx/XsCi7ZhIEXANOAYovcne93M\nnnD3eS2O6wZcBLya6rlFCk11dQ2Tp8xg0bIGPl4Uoffup3LU4XtwzTkqxERE8kmqPWMXAZ2BMcDF\n7r4wtv9E4G/bkHc48IG7f+LuYeBB4KQEx/0SuAHImU9wBn0tW3n5lVVdXcPIsTcyv2EUixsOpf9+\n57Bs3r388OvrKS1JbyEW5N875Skvl/OCPLdCyEsmpWLM3Wvc/Wvuvpe7/zZu/0Xufu425A0GFsRt\nL4zt28zMhgI7ubt60UTaMHnKDDpVjiNUEu0QCJWUMXjoj7l56l1ZHpmIiGyrlHrGAMysBDgO2B24\n293XmtnOwBp3X5viOU4Dvu7uY2Pbo4DD3P3i2LYBLwJnufunZjYLuNTd/5PgXOoZk4J18hnjWdPz\nglb7e66ZzuP3J2zDFBGRLNrhnrFYo/4LQH+gDHgKWAv8FOgC/CjFsSwEdonb3omtn23ZHdgPmB0r\nzAYAT5jZiYma+EePHk1lZSUA5eXlDB06lGHDhgFbLj9qW9tB3G7Y8BkrVs+mz67R7VWL5tDUWM/u\nlSU5MT5ta1vb2i707ebva2pqaJe7t/sFPAHcA5QA64DdYvu/DHyYyjlix4eAD4Fdid637C1gnyTH\nzwIObuM1z6RZs2YpT3k5k/Xxx9X++WPP86PHzPWhJz7oR4+Z658/9jz/+OPqtGcH+fdOecrL5bwg\nz60Q8mJ1S8J6p6j9cg2ALwLXebTpPt4nwKAUz4G7R4ALgeeBd4EH3X2umU00s28m+hGiz8YUkZg1\n6yM89Pfu3Hr9TxhSOpOuG/7EkNKZPHD75VRVVWZ5dCIisq1Svc/YKuCLHr3P2DrgIHf/2MyOAh51\n9/7pHmiCMXkqYxcJmlv/uJInXlrPEft3ZvL5/bI9HBERSUFHPJvyBaK3t2jmZtYVuBp4bgfHJyIp\nqlkc5qm/r6fI4Jxvl2d7OCIi0gFSLcYuBY4zs/8Rvd/YfcDHQBUwPk1jyynxDXnKU162sn7/2Cqa\nmuCEo7pRNag07XmJKE95ystOXpDnVgh5yaT0aUqP3mbiQOD7wKFEi7g/Ave6+7o0jk9EYl5/byOv\nvbuJrp2N0d/sme3hiIhIB0naM2ZmdxG9437OFVzqGZNC89isdfz+8VX84JvljPh6j2wPR0REtkGy\nnrH2irEIMNDdl6VrcNtLxZgUos9qG6noGUr7I49ERKRj7UgDv/7Gjwn6Wrby8iNrUEVxq0IsyO+l\n8pSnvOxkKS+zUmng1+UnERERkTRpb5myiRSKMXcPdeSgUqFlShEREckXO/psyrHA6o4dkoik4qOF\nDey+U2m2hyEiImmUyjLlU+7+aLKvtI8yBwR9LVt5uZf19oebOGfyEq6dUUuyq8BBfi+VpzzlZSdL\neZnVXjGmdUCRLGhqcm57NHpBeuf+xZjpszQiIkGVSs/YAN3aQiSzXnhtA9fdu4I+PUPcd/VAunRO\n9WEZIiKSi7a7Z8zd9S+ASIZtamhixhPRq2Jnn9hThZiISMDpb/kUBX0tW3m5k/XES+tZvjrCnjuX\n8PXPd0173rZSnvKUl528IM+tEPKSSenZlCKSOSce3Y1NDc7QIZ0oKlKvmIhI0CXtGctl6hkTERGR\nfLEjj0MSERERkTRSMZaioK9lKy8/s5SnPOUVTl6Q51YIecmoGBMRERHJIvWMiWRZuNG56vfL+dZR\n3fjCgV10g1cRkQDa0WdTikga/emldfzr3U0sqW3kiP27EAple0QiIpJJWqZMUdDXspWXnaw16yPc\n9+c1AJx7Si9CoW2/Khbk91J5ylNedrKUl1kqxkSy6N5n1rBho3Po3p35/P6dsz0cERHJAvWMiWTJ\nJ4vDnP2rxeBw+4QB7Da4NNtDEhGRNFHPmEgOWrshQv9eIQ7dp4sKMRGRApbxZUozG25m88xsvpmN\nT/D6j8zsf2b2ppm9bGZ7Z3qMiQR9LVt5mc86YI/O3P2LQYw9uTwjeR1FecpTXnbygjy3QshLJqPF\nmJkVAdOA44D9gJEJiq373f1Adz8YuAn4dSbHKJJJpSVGty5q3RQRKWQZ7RkzsyOAq939+Nj2FYC7\n+w1tHD8SGOXuJyR4TT1jIiIikhdyqWdsMLAgbnshcHjLg8zsfOAnQAnw1cwMTURERCTzMl2MJaoI\nW13ecvfbgNvMbARwFTA60clGjx5NZWUlAOXl5QwdOpRhw4YBW9aCO2r7lltuSev5lRecvPg+hJav\n9xx4BPtWlTLnny9nJC/T81Oe8pSXvryWmcrL7bzm72tqamiXu2fsCzgCeC5u+wpgfJLjDVjdxmue\nSbNmzVKe8nYoa3Ft2L9+0Sc+4ucLfX1dJO156aI85SkvO3lBnlsh5MXqloT1TqZ7xkLA+8AxwGLg\nX8BId58bd8we7v5h7PtvAVe5e6KlTM/k2EV21LUzapn9Rh3HHlbGhB9UZHs4IiKSQTnTM+buETO7\nEHie6Cc573T3uWY2EXjd3Z8GLjSzY4EGYBVwVibHKJIO73xUz+w36igtMc4+acduZSEiIsFSlOlA\nd3/O3fdy9z3d/frYvqtjhRjufom77+/uh7j7MfFXzbIpfg1YecrblqymJue2R1cBcPqx3enfu2P/\nDxTk91J5ylNedrKUl1kZL8ZECs0b729iXk0DvXsUMfJrPbI9HBERyTF6NqVIBrz27kbCYeeooWXZ\nHoqIiGRBsp4xFWMiIiIiaZasGNMyZYqCvpatvPzMUp7ylFc4eUGeWyHkJaNiTERERCSLtEwpkgbu\njlnCq9EiIlKAtEwpkkHuzoTbljPjidVs3NSU7eGIiEiOUzGWoqCvZStvx1VX13DOBVdyyFEjePCe\n6/njM3NpzEAtFsT3UnnKU152s5SXWZl+ULhIIFVX1zBy7I10qhwHFf9ll34HseS9W6hdOpDuVZXZ\nHp6IiOQw9YyJdIBzLriS+Q2jCJVsuY9YJFzHkNKZ3DF9UhZHJiIiuUA9YyJpVrs6vFUhBhAqKaN2\ndThLIxIRkXyhYixFQV/LVt6OqSgvIRKuA2DVojlA9MpYRXlJWnMheO+l8pSnvOxnKS+zVIyJdIAJ\nl46hvmbq5oIsEq6jvmYqEy4dk+WRiYhIrlPPmEgHqa6uYfKUGdSuDlNRXsKES8dQVVWZ5VGJiEgu\n0LMpRURERLJIDfwdIOhr2crbNq++vZFr7lhOQ7j1fwjyfW7KU57ycjMvyHMrhLxkVIyJbKP/zNvE\n1Xcs5+U3N/L8axuyPRwREclzWqYU2Qb/+3ATV0xbzqYG58QvdePiEb30DEoREWmXlilFOsDcmnom\n3BYtxIYf2ZVx31UhJiIiO07FWIqCvpatvPb98YW11G1yvvK5Mn56Rm+KihIXYvk4N+UpT3m5nxfk\nuRVCXjJ6NqVIiiaMrmCvXdfxnWO6E2qjEBMREdlW6hkTERERSTP1jImIiIjkKBVjKQr6WrbytrZy\nbSThPcTSkbWjlKc85RVGXpDnVgh5yWS8GDOz4WY2z8zmm9n4BK//2MzeNbO3zOwFM9s502OUwrZq\nXYSf/HopP//tcjbWN2V7OCIiEnAZ7RkzsyJgPnAM8BnwOjDC3efFHfNl4DV332Rm5wLD3H1EgnOp\nZ0w63NoNEX566zI+WhimalAJ/3dJP3p2C2V7WCIikudyqWfscOADd//E3cPAg8BJ8Qe4+0vuvim2\n+SowOMNjlAK1YWMT46ct56OFYXbqV8xN41SIiYhI+mW6GBsMLIjbXkjyYuts4Nm0jihFQV/LLvS8\njfVNTLhtOe9/0sDAPiFuvrgfvXtsXyGWa3NTnvKUF4y8IM+tEPKSyfR9xhJdnku41mhmo4BDgS+n\ndUQiQKjI6NrFqCgPMeXi/vTtpVvwiYhIZmS6Z+wI4Bp3Hx7bvgJwd7+hxXHHArcCR7v7ijbO5Wed\ndRaVlZUAlJeXM3ToUIYNGwZsqXi1re1UtxsjzgEHf4n+vYtzYjza1ra2ta3t/N1u/r6mpgaAe++9\nt82esUwXYyHgfaIN/IuBfwEj3X1u3DEHAw8Dx7n7R0nOpQZ+ERERyQs508Dv7hHgQuB54F3gQXef\na2YTzeybscNuBLoCD5vZm2b2p0yOsS3xla7ylJcrWcpTnvIKJy/IcyuEvGQy3hjj7s8Be7XYd3Xc\n91/L9JiksLg7j89ez/Ff6EqXThn9/4iIiEgrejalFBR3Z/rDq3hs9noO3bszN17UFzM99FtERNIr\nZ5YpRbLJ3ZnxxBoem72ekmI4/djuKsRERCTrVIylKOhr2YWQN/O5tTzw/FqKiuAXZ1dw2L5d0paV\nScpTnvIKIy/IcyuEvGR0MyUJtOrqGiZPmcHrb37AmvBgBu59Gr+6+CC+eFBZtocmIiICqGdMAqy6\nuoaRY2+kU+U4QiVlRMJ1rJp3C0/cdwVVVZVZHp2IiBSSZD1jKsYksM654ErmN4wiVLLlKlgkXMeQ\n0pncMX1SFkcmIiKFRg38HSDoa9lByVuwNMxjs9YBULs6vLkQW7VoDgChkjJqV4fTkt0sKO+l8pSn\nvNzKC/LcCiEvGfWMSd7bWN/Ey2/W8ed/buDtD+sBOHivTlSUl7Cyoa7VlbGK8pJsDVVERKQVLVNK\nXrv3mTU8/Le11G2K/lno3MkYdkgZZxzXg4YNi1r1jNXXTOWB2y9Xz5iIiGRUsmVKXRmTvFe3ydm3\nqpTjv9CNrxxaRlnn5tX3Sh64/XImT5lB7eowFeUlTFAhJiIiOUY9YykK+lp2LudFmpylKxsTvvat\nL3XjzisHMO2yAZzwxW5xhVhUVVUld0yfxMXnHM8d0ydlpBDL5fdSecpTXv7mBXluhZCXjK6MSc5a\nsqKR5+as57lXN1BabNx79cBWd8zv3SNE7x6hLI1QRERkx6lnTHJKU5Pz0hvRZvw33t9E82/xgD4h\npv60PxXl+v+DiIjkH/WMSd4wg/v/spaPF4UpKYYvDS3jG1/oxtAhnSgq0nMkRUQkeNQzlqKgr2Vn\nKq+6uoZzLriSo44dyTkXXEl1dc1Wr5sZo4b34KLTe/HI9Ttx5Q8rOGTvzjtciKmvQ3nKU16+5wV5\nboWQl4yKsQLXXBxdOen3CYujjhBudBYuC/Pya/M57Qc3ML9hFBu6fpv5DaMYOfbGVpnDDu3KycO6\n071MfzxFRCT41DNWwBI9u7H23Vs48wfn07PPznTtUsT3j+/Z6ueWrmxk4oxawo1OQzj6FW50+pYX\n89srBrQ6/tOlYUZPXEz167ewy9CxejyRiIgUHPWMFZjGiFPzWZjlqyPUrm5k+eoIy1dFCIXg0jP6\nbD5u8pQZmwsxiD4qqGK/S/jd7bdTddglDOgTSliMucO8moZW+4uLIwnH06XUGNS3mMUlvlUh1pyZ\n7scTiYiI5DKtA6UoF3qqIhFn+apG5lbX8/KbdTw7Z33Cc6xeF2HsdUv4+W+X8+sHVjHz2bX85dUN\nvPxG3VbHtfXsxgF9jLEnlycsxCB6O4lpl/Xn9p8N4O6rBnL/tYN4+LrB3DFhYMLj+/YqZubEQRx1\ncFci4bqt8jL1eCL1dShPecrL97wgz60Q8pLRlbF2VFfXMHnKDOa+/xH7PPxXJlw6pkNuHLpmfYSN\n9c6mBmdTfRObGpyPq2u48aapdKoax4au/2V+w0GMHHsjd//mUq6+rxMr10RoiluZLSmG4Ud0bXXv\nrV49Quw2uIQ+PUP0LQ9RUR6ioryYvr1CuPvm49t6duP+u3dhxNd6tDn20hJj36pO2zznCZeO2bws\n2pxVXzOVCbdfvs3nEhERCYq87hkbc/7PO6w4amnFmggffFjNhZfeTNc9Lt7ybMPqqTxwR+tH6kx7\neBV1m5rYVO9saoj9Gnam/rQ/xaHWS8Rfu/BTIk1b72uzp6pkJotKf0R92CnvXkTf8uLNRdZ5p/ai\ntGT7PmmYqGcs3c9ubC5uNz+eKE2/fyIiIrkkWc9YXhdjR4+Zy6p5t3DRhRdSXrEL4bDznWN7UFLc\neq5X376c9RubqG9wGhqdhtivd145kC6dWq/WfuOSBcx95dcpN5yf8OMFbKxv/V4+efNOdOvS+vxn\n/OIzIhGnc6nRuVMRnUqNWU/cQMV+l7Q6tuea6dw+/VeUdwslnNuOUHEkIiKSfsmKsbzuGQuVlNFr\n70uYPOUufvvoamY8uYaN9U0Jj31rfj1vvl/Pe9UNfLggzKdLG1myIkJDOHEx2r9PMaXFTQl7qhI1\nnJ9/Wi8uPaM3V/6wD5POrWDKuH5Mu6w/nUsTF0/3XzuIB381mHuuHsTvrhjArT/pz+f3L2uzp6pv\neXGHF2KQnWc3QrB7A4I8N+UpT3nZywvy3AohL5m87xkLlZTRp6dx6le7U1psCZcEAa46uw9mRqcS\nozTuq1sb97K6+6qBnLOkG/MT9FQlajg/4Yvddngu6qkSEREpPHm9TPmV8z5J632q1FMlIiIiHSGn\nesbMbDhwC9El0jvd/YYWr38p9vqBwHfd/bE2zuNHj5mr4khERERyXs70jJlZETANOA7YDxhpZnu3\nOOwT4Czg/vbON6R0ZloLMVBPlfJyO0t5ylNe4eQFeW6FkJdMpnvGDgc+cPdPAMzsQeAkYF7zAe7+\naey1di/Z6RE6IiIiku8yukxpZqcCx7n72Nj2KOBwdx+X4Ni7gaeSLVPma7+biIiIFJZcejZlokFs\nd9WeI74AAA7aSURBVEU1evRoKisrASgvL2fo0KEMGzYM2HL5Udva1ra2ta1tbWs709vN39fU1NAu\nd8/YF3AE8Fzc9hXA+DaOvRs4Jcm5PJNmzZqlPOXlXJbylKe8wskL8twKIS9WtySsaYraL9c61OvA\nHma2q5mVAiOAJ5Mc3/F3ORURERHJIdm6tcWtbLm1xfVmNhF43d2fNrPPAY8D5cAmYIm7H5DgPJ7p\nsYuIiIhsj5y6z1hHUTEmIiIi+SJn7jOWz+Ib8pSnvFzJUp7ylFc4eUGeWyHkJaNiTERERCSLtEwp\nIiIikmZaphQRERHJUSrGUhT0tWzl5WeW8pSnvMLJC/LcCiEvGRVjIiIiIlmknjERERGRNFPPmIiI\niEiOUjGWoqCvZSsvP7OUpzzlFU5ekOdWCHnJqBgTERERySL1jImIiIikmXrGRERERHKUirEUBX0t\nW3n5maU85SmvcPKCPLdCyEtGxZiIiIhIFqlnTERERCTN1DMmIiIikqNUjKUo6GvZysvPLOUpT3mF\nkxfkuRVCXjIqxkRERESySD1jIiIiImmmnjERERGRHKViLEVBX8tWXn5mKU95yiucvCDPrRDyklEx\nJiIiIpJF6hkTERERSTP1jImIiIjkqIwXY2Y23Mzmmdl8Mxuf4PVSM3vQzD4wszlmtkumx5hI0Ney\nlZefWcpTnvIKJy/IcyuEvGQyWoyZWREwDTgO2A8YaWZ7tzjsbGClu+8J3ALcmMkxtuWtt95SnvJy\nLkt5ylNe4eQFeW6FkJdMpq+MHQ584O6fuHsYeBA4qcUxJwH3xr5/BDgmg+Nr0+rVq5WnvJzLUp7y\nlFc4eUGeWyHkJZPpYmwwsCBue2FsX8Jj3D0CrDaz3pkZnoiIiEhmZboYS/QpgpYfiWx5jCU4JuNq\namqUp7ycy1Ke8pRXOHlBnlsh5CWT0VtbmNkRwDXuPjy2fQXg7n5D3DHPxo55zcxCwGJ375fgXFkv\n0ERERERS1datLYozPI7XgT3MbFdgMTACGNnimKfg/7d3pkFWFWcYfl6cUQEF10gMQTQR14hbkCiK\nicRCTYgVtUoxETVLxdJItBRFrHKJiUtUsKzyRwxqgiFBcYkaBVnUaBQUZYcoBhCQAhE3KJEofPnR\nPdTxcjdmTt87A99TdWrO0t3v6Tvd3/1urwwCpgJnAZOLJVQqQ47jOI7jOG2JmjpjZrZB0iXAs4Qu\n0pFmNl/SDcBrZvYUMBIYJWkBsJrgsDmO4ziO42yVtNkV+B3HcRzHcbYG2twK/JJukzRf0gxJj0jq\nlHk2NC4WO1/SyTnpnSlpjqQNko7M3G+Q9ICkWZLmxvFvSbTis8MkvRyfz5S0fUq9+LybpDWSLm+p\nVjk9Sf0kTYv5ek3Sd1PqxWe5l5WC9HvGRYunS3pV0tF5axTR/HVcUHm2pFtS60XNKyRtTD3juVy9\nz1mn7KLUOWt1lTRZ0rz4P7s0pV7UbCfpDUlP1ECrs6SH4/9trqRjEutdFuv7LEl/zcNGFqQ/UtJK\nSbMy93aV9KykNyWNl9Q5sV6yelBML/Ms93peSi+VHSvxedbcTpfEzNrUAfQD2sXzW4Cb4/nBwHRC\n12t34G1iy18L9Q4A9ieMXTsyc/8cYHQ8bw8sArol0toOmAkcGq93TZm3zPOxwBjg8pz+d6Xy1xPo\nEs8PAZYl1jsoRVkp0B4PnBzPTwGeyzP9InonErr/G+L1Hin1okZXYFws+7sl1ipa73PWaBfLwj5A\nIzADODBhnroAh8fznYA3U+pFncuAB4EnalA+HgAuiOcNQKeEWnsDC4Ht4/UY4LycNfoAhwOzMvdu\nBYbE86uAWxLrJasHxfTi/ST1vET+ktmxEno1tdPljjbXMmZmE81sY7ycQigoAAOAv5vZF2a2GFhA\nWGS2pXpvmtkCNl9yw4COCjM+OwDrgU8SaZ0MzDSzOTHchxZLTyI9JP0I+C8wt6U6lfTMbKaZrYjn\nc4EdJDWm0iMsLJx7WSlgI9D0K3kX4N2c0y/kIsIXwRcAZvZ+Yj2A4cCVNdApV+/zpJpFqXPDzFaY\n2Yx4vhaYz+brLuaGpK7AqcCfUmlktHYGjjez+wFiXWuRfayC7Qg2uYFgk5fnmbiZvQR8WHA7u0j5\nn4HTU+qlrAcl8geJ6nkJvWR2rIRere10SdqcM1bAhcDT8bxwQdl3SWjYCK1GnxJmhS4GbjezVMv5\n9gCQNC525yX9ApTUARgC3EDxteFSap8JTI9fhqmoRVm5DLhd0hLCll5Dc06/kB7ACZKmSHoudXO7\npB8CS81sdkqdElwIPJMg3WoWpU6CpO6EX+1TE8o0fanWYqDwfsD7ku6P3aJ/lNQ+lZiZLQfuAJYQ\n6vNHZjYxlV6Gr5jZyvgOK4A9a6DZRKp6sIk61POa2jFqb6dLUuulLapC0gRgr+wtggEZZmZPxjDD\ngM/N7G+ZMIVUZXSq0StCL+ALQlfD7sCLkibGlpa8tRqA44Cjgc+ASZKmmdlzZTPWfL0bgOFm9qmk\npjhV0Uy9priHADcD30+s1+yyUq02oTthsJk9Hh3M+9iCfG2h3rWEMrKLmfWW9G3gIcIXYiq9a/hy\nflrstG9hvR/dUr1ir1DkXnLHRdJOhB93g2MLWQqN04CVZjZD0omk/5HVABwJXGxm0ySNAK4Grksh\nJmkXQivVPsDHwFhJAxOVk7qTuB40abQn2LJc63kFcrdjFbiInO10c2mVzpiZlf0wJA0iNLd/L3N7\nGfD1zHVXqmymrqRXgoHAuNhkvErSvwnO0uIEWsuAF8zsQwBJTxMMXUVnrJl6xwBnSLqNMD5tg6R1\nZnZPIr2mLpRHgZ9Wcmhz0Gt2WalWW9IoMxscw42VNHKL33LL9H5F+Pwws9fiYNvdzWx13nqSDiWM\ntZup4K13BV6X1MvM3stbL6NbrN7nyTKgW+a6WeViS4hdamOBUWb2j4RSxwEDJJ1KGOO6s6S/mNl5\nifSWEVpUpsXrsYQxVanoByw0sw8AJD0KHAukdsZWStrLzFZK6gI0u/xXSw3qQRPfIEE9r8BScrZj\nFRiUt51uLm2um1JSf0IX2gAzW5959ARwtqTtJe0LfBN4NW/5zPkSYmWQ1BHoDfwnkdZ44DBJO0bj\n3ReYl6PWl/TM7AQz28/M9gNGAL+vxhFrrl6cgfQUcLWZTclZZzM9alNW3pXUF0DSScBbOadfyOPA\nSVGvB9CYyoCZ2Rwz6xLLyL6EL94jEhrocvU+TzYtSq0wE+9sQllJyX3APDO7K6WImV1jZt1inT4b\nmJzQESN23S2NZRFC2czbZmVZAvSONlJRb34CHbG5LTk/ng8C8naov6RXg3qwSa9G9bzw80xtxwr1\nam2nS2N1mjnQ3IMw2Pod4I143JN5NpQwG2o+cYZEDnqnE7z1dYTxYc/E+x0JTahz4tHiGYeltOKz\ngVFnFjnNoCmnlwlzXR55q/BZDgPWxP/n9Pi3xbNoKnyeuZeVAu1jgWkxP68QjFjKetEIjAJmR92+\nKfUKtBeSfjZlyXqfs05/wqzGBYQfBynzdBywgTBrs6nc96/B/6svtZlN2ZPg4M4gtHZ0Tqx3XazP\nswiD6RtzTn80oaV0PcH5u4DQczAxlpkJhC62lHrJ6kExvYLnudbzEvlrSGXHSujV1E6XO3zRV8dx\nHMdxnDrS5ropHcdxHMdxtibcGXMcx3Ecx6kj7ow5juM4juPUEXfGHMdxHMdx6og7Y47jOI7jOHXE\nnTHHcRzHcZw64s6Y4zhOBSSdL6nsXoeS7pZUcVeMgjh7SnpP0t4te0PHcdoy7ow5jtMqkbSHpHsk\nLZL0maQVkibElbKbwjwft0wZWBB3kKQ1meu+MVzT8b6kSZKOreI9GoHfAtdX8dqbFm6Mm2RnNVdJ\nelLSAZsCm60iLFB6YxVpO46zleLOmOM4rZVHCfu9XgDsD5wGPAPsngljhB0WbopOEwXPCq8PAroQ\nVqFfBfxT0h4V3uMsYJ2ZvdSMPDRtft6FsAFxe+LeexkeAM6Nm107jrMN4s6Y4zitjrhfaR/ClkTP\nm9lSM3vdzO40s4cKgo8BdgQuriLpVWb2npnNBW4COgPHVIhzDgV7VEpqJ+l2SR9IWi1pOLBdkbjr\nzaxJcwYwHDhQ0g5NAeK7LAd+XMX7O46zFeLOmOM4rZG18RiQdVzKhL0RuFZSpwphBSCpA3AhobXs\n8wpx+hD2r8tyBfAz4BfAdwiO2LllhaWdCZt0z7LNN3l+ldBa5zjONog7Y47jtDrMbAMwCPgJ8JGk\nlyX9QVKvElHuBVYDV5dJVsCiOJZsDfAbwkbWk0pGCC10nQkbzWcZDNxqZo+Y2VvxekWRJE6RtCZq\nfgwcT3GnbTnQvcy7O46zFePOmOM4rRIzewzYG/gB8DShBWqKpM0crui8DQMuLTMz0YATgSMILVQL\ngfNj3FK0j38/a7oRW9++CkzJ6BswtUj8F4DDgJ5AL2AyMEHS1wrCrctoOY6zjeHOmOM4rRYz+5+Z\nTTKzm8ysDzASuF5SQ5GwY4HZlJ+ZuNjM3jazh2O4x4oM/M+ymuDE7drMLHxqZovMbKGZTQN+DnQC\nflkQbjfChALHcbZB3BlzHKctMR9oIAzYL8ZVhO7NQ6pIaxTQSJmB/2b2OTAPODhz7xNCt2XvguCl\nulAL2Qh0KLh3KPBGlfEdx9nKcGfMcZxWh6Td4jpg50r6lqTuks4CrgQmmtnaYvHM7F/AOOCSYskW\nhDVgBDBUUrkuwvGEQfxZ7gKGSDpDUg9JIwhdl4XsIGmveBwI3A10JDM7M2ofRVi2w3GcbRB3xhzH\naY2sBV4BLgWeB+YQlqJ4kDDeq4nCtcQgDOJvLPKsWNj7CDMhB5d5l3uB/gXrgN0B3B+fTSE4eg8W\niduPMDh/eQx3FHCmmb2YCXM68I6ZvVzmHRzH2YpR+HHoOI7jlELSaGCumf0uQdpTgTvNbEzeaTuO\n0zbwljHHcZzKDAE+yTtRSXsCD7sj5jjbNt4y5jiO4ziOU0e8ZcxxHMdxHKeOuDPmOI7jOI5TR9wZ\ncxzHcRzHqSPujDmO4ziO49QRd8Ycx3Ecx3HqiDtjjuM4juM4dcSdMcdxHMdxnDryf3Ta+A7NYZxw\nAAAAAElFTkSuQmCC\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fb54c303b38>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "plt.style.use('classic')\n",
    "%matplotlib inline\n",
    "\n",
    "acc_test = sorted(acc_test.items())\n",
    "new_acc = []\n",
    "for i in range(len(acc_test)):\n",
    "    new_acc.append(acc_test[i][1])\n",
    "acc_test_values = new_acc \n",
    "\n",
    "fig1 = plt.figure(figsize=(10, 6), dpi=100)\n",
    "x = snrs\n",
    "y = list(acc_test_values)\n",
    "plt.plot(x, y, marker=\"o\", linewidth=2.0, linestyle='dashed', color='royalblue')\n",
    "plt.axis([-20, 20, 0, 1])\n",
    "plt.xticks(np.arange(min(x), max(x)+1, 2.0))\n",
    "plt.yticks(np.arange(0, 1, 0.10))\n",
    "\n",
    "ttl = plt.title('SNR vs Accuracy', fontsize=16)\n",
    "ttl.set_weight('bold')\n",
    "plt.xlabel('SNR (dB)', fontsize=14)\n",
    "plt.ylabel('Test accuracy', fontsize=14)\n",
    "plt.grid()\n",
    "\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "metadata": {
    "collapsed": false
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Confusion Matrix\n",
      "       8PSK  BPSK  CPFSK  GFSK  PAM4  QAM16  QAM64  QPSK\n",
      "8PSK   0.52  0.00   0.03  0.00  0.00   0.03   0.01  0.41\n",
      "BPSK   0.01  0.92   0.00  0.00  0.02   0.02   0.01  0.03\n",
      "CPFSK  0.00  0.00   0.96  0.03  0.00   0.00   0.00  0.01\n",
      "GFSK   0.00  0.00   0.03  0.96  0.00   0.00   0.00  0.00\n",
      "PAM4   0.00  0.07   0.00  0.00  0.90   0.02   0.01  0.00\n",
      "QAM16  0.11  0.00   0.00  0.00  0.00   0.42   0.34  0.13\n",
      "QAM64  0.02  0.00   0.00  0.00  0.00   0.44   0.54  0.01\n",
      "QPSK   0.42  0.00   0.01  0.00  0.00   0.03   0.02  0.53\n"
     ]
    },
    {
     "data": {
      "image/png": "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\n",
      "text/plain": [
       "<matplotlib.figure.Figure at 0x7fb4eeefd320>"
      ]
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "source": [
    "# Confusion Matrix\n",
    "\n",
    "with tf.Session() as sess:\n",
    "    saver.restore(sess, path)\n",
    "    Z = logits.eval(feed_dict = {X : X_test[18]})\n",
    "    predicted_18dB = np.argmax(Z, axis = 1)\n",
    "    \n",
    "from sklearn.metrics import confusion_matrix\n",
    "%matplotlib inline\n",
    "\n",
    "classes = ['8PSK', 'BPSK', 'CPFSK', 'GFSK', 'PAM4', 'QAM16', 'QAM64', 'QPSK']\n",
    "conf_matrix = confusion_matrix(predicted_18dB, y_test[18])  \n",
    "\n",
    "conf_matrix = conf_matrix.astype('float') / conf_matrix.sum(axis=1)[:, np.newaxis]\n",
    "conf_matrix = conf_matrix.round(decimals = 2)\n",
    "\n",
    "import pandas as pd\n",
    "\n",
    "df = pd.DataFrame(data = conf_matrix, columns = classes, index = classes) \n",
    "print(\"Confusion Matrix\")\n",
    "print(df)\n",
    "\n",
    "plt.imshow(conf_matrix, interpolation = 'nearest', cmap = plt.cm.Purples)\n",
    "ticks = np.arange(len(classes))\n",
    "plt.title(\"Confusion Matrix\")\n",
    "plt.xticks(ticks, classes, rotation=45)\n",
    "plt.yticks(ticks, classes)\n",
    "\n",
    "plt.ylabel('True class')\n",
    "plt.xlabel('Predicted class')\n",
    "\n",
    "plt.tight_layout()\n",
    "plt.colorbar()\n",
    "plt.show()"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {
    "collapsed": true
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "kernelspec": {
   "display_name": "Python [default]",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.5.2"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 1
}
